home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1998 September / Macworld (1998-09).dmg / Shareware World / Info / For Developers / MacZoop 1.8.3 / Required Classes / Z Sources / ZComrade.cpp < prev    next >
Text File  |  1998-06-11  |  8KB  |  313 lines

  1. /*************************************************************************************************
  2. *
  3. *
  4. *            MacZoop - "the framework for the rest of us"     
  5. *
  6. *
  7. *
  8. *            ZComrade.cpp    -- an object that can maintain loose links between objects
  9. *
  10. *
  11. *
  12. *
  13. *
  14. *            © 1996, Graham Cox
  15. *
  16. *
  17. *
  18. *
  19. *************************************************************************************************/
  20.  
  21.  
  22. #include    "ZComrade.h"
  23. #include    "ZObjectArray.cpp"
  24. #include    "MacZoop.h"
  25.  
  26.  
  27. // this is a fudge to get around a limitation of the language- ZComrade requires ZObjectArray
  28. // for its lists, but ZObjectArray IS a ZComrade. Thus, since we are not allowed forward/
  29. // circular cross-dependencies like this, this struct is used to "pull" the declaration forward
  30. // so that everything compiles correctly.
  31.  
  32. struct ZComradeList : ZObjectArray<ZComrade>
  33. {
  34. };
  35.  
  36.  
  37. CLASSCONSTRUCTOR( ZComrade );
  38.  
  39. /*---------------------------------***  CONSTRUCTOR  ***--------------------------------*/
  40.  
  41.  
  42. ZComrade::ZComrade()
  43. {
  44.     classID = CLASS_ZComrade;
  45.     talkers = listeners = NULL;
  46. }
  47.  
  48. /*---------------------------------***  DESTRUCTOR  ***---------------------------------*/
  49.  
  50. ZComrade::~ZComrade()
  51. {
  52.     // when we are destroyed, we need to make sure that we remove ourselves
  53.     // from any talker's list that we are part of, and make sure that any listeners
  54.     // that are listening to us no longer do so.
  55.     
  56.     long        n;
  57.     ZComrade*    aComrade;
  58.     
  59.     if( listeners )
  60.     {
  61.         n = listeners->CountItems();
  62.         
  63.         do
  64.         {
  65.             aComrade = listeners->GetObject( n );
  66.             
  67.             if( aComrade )
  68.                 aComrade->RemoveTalker( this );
  69.         }
  70.         while( --n );
  71.         
  72.         ForgetObject( listeners );
  73.     }
  74.     
  75.     if( talkers )
  76.     {
  77.         n = talkers->CountItems();
  78.         
  79.         do
  80.         {
  81.             aComrade = talkers->GetObject( n );
  82.             
  83.             if( aComrade )
  84.                 aComrade->RemoveListener( this );
  85.         }
  86.         while( --n );
  87.     
  88.         ForgetObject( talkers );
  89.     }
  90. }
  91.  
  92.  
  93. /*--------------------------------***  SENDMESSAGE  ***---------------------------------*/
  94. /*    
  95. transmit a message to anyone who is listening
  96. ----------------------------------------------------------------------------------------*/
  97.  
  98. void        ZComrade::SendMessage( long aMessage, void* msgData )
  99. {
  100.     // send the message to all of the listeners of this object
  101.  
  102.     long        n;
  103.     ZComrade*    aListener;
  104.     
  105.     if( listeners )
  106.     {
  107.         n = listeners->CountItems();
  108.         
  109.         do
  110.         {
  111.             aListener = listeners->GetObject( n );    
  112.             
  113.             if( aListener )
  114.                 aListener->ReceiveMessage( this, aMessage, msgData );
  115.         }
  116.         while( --n );    
  117.     }
  118. }
  119.  
  120. /*--------------------------------***  SENDMESSAGE  ***---------------------------------*/
  121. /*    
  122. transmit a message to anyone who is listening (via a message object)
  123. ----------------------------------------------------------------------------------------*/
  124.  
  125. void        ZComrade::SendMessage( ZMessage* aMessage )
  126. {
  127.     // send the message object to all of the listeners of this object
  128.     
  129.     long        n;
  130.     ZComrade*    aListener;
  131.     
  132.     if( listeners )
  133.     {
  134.         n = listeners->CountItems();
  135.         
  136.         do
  137.         {
  138.             aListener = listeners->GetObject( n );    
  139.             
  140.             if( aListener )
  141.                 aListener->ReceiveMessage( this, aMessage );
  142.         }
  143.         while( --n );    
  144.     }
  145. }
  146.  
  147.  
  148. /*-------------------------------***  RECEIVEMESSAGE  ***-------------------------------*/
  149. /*    
  150. a message was transmitted by someone we have earlier elected to listen to
  151. ----------------------------------------------------------------------------------------*/
  152.  
  153. void        ZComrade::ReceiveMessage( ZComrade* aSender, long theMessage, void* msgData )
  154. {
  155.     // override to do something useful
  156. }
  157.  
  158.  
  159. /*------------------------------***  RECEIVEMESSAGE  ***--------------------------------*/
  160. /*    
  161. receive a message in a message object from one of our transmitting comrades
  162. ----------------------------------------------------------------------------------------*/
  163.  
  164. void        ZComrade::ReceiveMessage( ZComrade* aSender, ZMessage* aMessage )
  165. {
  166.     // override to do something useful
  167. }
  168.  
  169. /*---------------------------------***  LISTENTO  ***-----------------------------------*/
  170. /*    
  171. elect to listen to another comrade. We will receive any messages transmitted by that
  172. object whenever it sends them
  173. ----------------------------------------------------------------------------------------*/
  174.  
  175. void        ZComrade::ListenTo( ZComrade* aSender )
  176. {
  177.     // add this to the sender's list of listeners, and the sender to our list of talkers
  178.     
  179.     FailOSErr((aSender == NULL)? paramErr : noErr );
  180.     
  181.     // make sure we are not already listening to this one- references must be
  182.     // included exactly once
  183.     
  184.     if(( talkers == NULL ) || !talkers->Contains( aSender ))
  185.     {
  186.         aSender->AddListener( this );
  187.         AddTalker( aSender );
  188.     }
  189. }
  190.  
  191.  
  192. /*-----------------------------***  STOPLISTENINGTO  ***-------------------------------*/
  193. /*    
  194. we no longer want to receive messages from this transmitter
  195. ----------------------------------------------------------------------------------------*/
  196.  
  197. void        ZComrade::StopListeningTo( ZComrade* aSender )
  198. {
  199.     // remove this from the sender's list of listeners, and remove it from our list of talkers
  200.     
  201.     FailOSErr((aSender == NULL)? paramErr : noErr );
  202.     
  203.     // make sure we are really listening to it
  204.     
  205.     if (talkers && talkers->Contains( aSender ))
  206.     {
  207.         RemoveTalker( aSender );
  208.         aSender->RemoveListener( this );
  209.     }
  210. }
  211.  
  212.  
  213. /*---------------------------------***  ADDTALKER  ***----------------------------------*/
  214. /*    
  215. add a talker to our list of talkers
  216. ----------------------------------------------------------------------------------------*/
  217.  
  218. void        ZComrade::AddTalker( ZComrade* aTalker )
  219. {
  220.     // add the talker to the list of talkers
  221.     
  222.     if (talkers == NULL)
  223.         FailNIL( talkers = new ZComradeList());
  224.         
  225.     talkers->AppendItem( aTalker );
  226. }
  227.  
  228. /*-------------------------------***  ADDLISTENER  ***----------------------------------*/
  229. /*    
  230. add a listener to our list of listeners
  231. ----------------------------------------------------------------------------------------*/
  232.  
  233. void        ZComrade::AddListener( ZComrade* aListener )
  234. {
  235.     // add the listener to the list of listeners
  236.     
  237.     if (listeners == NULL)
  238.         FailNIL( listeners = new ZComradeList());
  239.         
  240.     listeners->AppendItem( aListener );
  241. }
  242.  
  243.  
  244. /*--------------------------------***  REMOVETALKER  ***--------------------------------*/
  245. /*    
  246. remove the talker from our list of talkers
  247. ----------------------------------------------------------------------------------------*/
  248.  
  249. void        ZComrade::RemoveTalker( ZComrade* aTalker )
  250. {
  251.     // remove this talker from the list of talkers
  252.     
  253.     if( talkers )
  254.     {
  255.         talkers->DeleteObject( aTalker );
  256.         
  257.         if( talkers->CountItems() <= 0 )
  258.             ForgetObject( talkers );
  259.     }
  260. }
  261.  
  262.  
  263. /*-------------------------------***  REMOVELISTENER  ***-------------------------------*/
  264. /*    
  265. remove the listener from our list of listeners
  266. ----------------------------------------------------------------------------------------*/
  267.  
  268. void        ZComrade::RemoveListener( ZComrade* aListener )
  269. {
  270.     // remove this listener from the list of listeners
  271.     
  272.     if( listeners )
  273.     {
  274.         listeners->DeleteObject( aListener );
  275.         
  276.         if( listeners->CountItems() <= 0 )
  277.             ForgetObject( listeners );
  278.     }
  279. }
  280.  
  281.  
  282. /*--------------------------------***  WRITETOSTREAM  ***-------------------------------*/
  283. /*    
  284. write talkers and listener refs to stream
  285. ----------------------------------------------------------------------------------------*/
  286.  
  287. void    ZComrade::WriteToStream( ZStream* aStream )
  288. {
  289. #if _MACZOOP_STREAMS
  290.     // note: ZStream permits NULL objects to be written to the stream, so we don't even
  291.     // need to check whether they're NULL or not.
  292.     
  293.     aStream->WriteObject( talkers );
  294.     aStream->WriteObject( listeners );
  295. #endif
  296. }
  297.  
  298.  
  299. /*-------------------------------***  READFROMSTREAM  ***-------------------------------*/
  300. /*    
  301. read from the stream- this re-establishes the entire comrade linkage from the stream.
  302. You should only call this when this comrade is first made, since any existing talkers
  303. or listeners objects will be left dangling.
  304. ----------------------------------------------------------------------------------------*/
  305.  
  306. void    ZComrade::ReadFromStream( ZStream* aStream )
  307. {
  308. #if _MACZOOP_STREAMS
  309.     talkers     = (ZComradeList*) aStream->ReadObject();
  310.     listeners     = (ZComradeList*) aStream->ReadObject();
  311. #endif
  312. }
  313.